

from qtpy import QtCore
from qtpy import QtWidgets
from qtpy import QtGui


class EditableComboBox(QtWidgets.QComboBox):
    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        # 允许编辑
        self.setEditable(True)

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Return or event.key() == QtCore.Qt.Key_Enter:
            current_text = self.currentText()
            if current_text and self.findText(current_text) == -1:
                # 如果当前文本非空，则插入新项
                self.addItem(current_text)
            # 添加完下拉列表选项后显示列表
            self.showPopup()
            # 清除 lineEdit 的内容
            self.lineEdit().setText('')
            # 阻止默认的回车键插入行为
            event.ignore()
        else:
            # 对于其他按键，调用基类的 keyPressEvent 方法
            super().keyPressEvent(event)


class ColorButton(QtWidgets.QPushButton):
    def __init__(self, text, color, parent=None) -> None:
        super().__init__(text, parent)
        # 设置背景颜色
        palette = QtGui.QPalette()

        if isinstance(color, tuple):
            temp_color = QtGui.QColor(*color)
        elif isinstance(color, str):
            temp_color = QtGui.QColor(color)
        else:
            temp_color = color
        if temp_color is not None:
            palette.setColor(QtGui.QPalette.Button, temp_color)
            self.setPalette(palette)
        self.setAutoFillBackground(True)

        # 设置文本颜色
        self.setStyleSheet("color: white;")  # 设置文本颜色为白色


class CreateLabelDialog(QtWidgets.QDialog):
    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        # 设置窗口标题
        self.setWindowTitle(self.tr("创建标签"))
        self.setModal(True)
        # 垂直布局
        self.v_layout = QtWidgets.QVBoxLayout()
        # 标签
        self.label_name_line_edit = QtWidgets.QLineEdit(self)
        # 设置提示信息
        self.label_name_line_edit.setPlaceholderText(self.tr("标签名称"))
        # 创建添加属性按钮
        self.add_attr_bt = QtWidgets.QPushButton(self.tr("添加属性"), self)
        self.add_attr_bt.clicked.connect(self.add_attr_clicked)
        h_layout = QtWidgets.QHBoxLayout()
        h_layout.addWidget(self.label_name_line_edit)
        h_layout.addWidget(self.add_attr_bt)

        # 确认取消按钮
        self.buttonBox = QtWidgets.QDialogButtonBox(
            QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel,
            QtCore.Qt.Horizontal,
            self
        )
        self.buttonBox.accepted.connect(self.onAccepted)
        self.buttonBox.rejected.connect(self.reject)
        # 添加布局
        self.v_layout.addLayout(h_layout)
        self.v_layout.addWidget(self.buttonBox)
        # 设置对话框的布局
        self.setLayout(self.v_layout)
        self.data = {"attr": []}
        self.label_color = None

    def getLabelColor(self):
        import random
        """设置标签颜色"""
        if True and self.label_color is None:
            # 随机生成颜色
            red = random.randint(0, 255)
            green = random.randint(0, 255)
            blue = random.randint(0, 255)
            self.label_color = (red, green, blue, 150)
            # self.label_color = QtGui.QColor(red, green, blue)
            # self.label_color = QtGui.QColor(red, green, blue).name(QtGui.QColor.HexRgb)
        else:
            # 使用颜色对话框获取颜色
            # TODO
            self.label_color = None

        return self.label_color

    def loadLabel(self, label_info=None, label_name_readonly=False):
        """根据数据内容自动生成对话框控件"""

        # label_info = {'name': '111', 'attributes': [{'attr_name': '222', 'attr_value': ['333']}]}
        if label_info is not None:
            self.label_name_line_edit.setText(label_info["name"])
            # 设置只读，创建的标签不允许修改名称
            self.label_name_line_edit.setReadOnly(label_name_readonly)
            for attr in label_info["attributes"]:
                self.add_attr(attr["attr_name"], attr["attr_value"])
            self.label_color = label_info["color"]

    def onAccepted(self):
        """如果没有输入则不会退出窗口"""
        if self.label_name_line_edit.text():
            self.accept()

    def getLabelData(self):
        """获取标签数据"""
        ret = {}
        ret["name"] = self.label_name_line_edit.text()
        # 设置颜色
        ret["color"] = self.getLabelColor()

        ret["attributes"] = []

        for onedata in self.data["attr"]:
            # 属性名称
            attr_name = onedata["attr_name"].text()
            if attr_name == "":
                continue
            # 属性的值
            attr_value = []
            for index in range(onedata["attr_value"].count()):
                value = onedata["attr_value"].itemText(index)
                attr_value.append(value)
            # 如果只有属性名称，没有对应的值，则该记录不要
            if not attr_value:
                continue
            ret["attributes"].append({
                "attr_name": attr_name,
                "attr_value": attr_value
            })
        return ret

    def add_attr_clicked(self):
        "单击事件"
        self.add_attr()

    def add_attr(self, attr_name="", attr_value=[]):
        """添加属性控件"""
        self.v_layout.removeWidget(self.buttonBox)

        attr_edit = QtWidgets.QLineEdit(self)
        attr_edit.setPlaceholderText(self.tr("属性名称"))

        if attr_name != "":
            attr_edit.setText(attr_name)

        editabel_combobox = EditableComboBox(self)

        for value in attr_value:
            editabel_combobox.addItem(value)

        self.data["attr"].append(
            {
                "attr_name": attr_edit,
                "attr_value": editabel_combobox
            }
        )
        h_layout = QtWidgets.QHBoxLayout()
        h_layout.addWidget(attr_edit)
        h_layout.addWidget(editabel_combobox)
        self.v_layout.addLayout(h_layout)

        self.v_layout.addWidget(self.buttonBox)

        self.setLayout(self.v_layout)

    def keyPressEvent(self, event) -> None:
        # 检查是否是回车键
        if event.key() == QtCore.Qt.Key_Return or event.key() == QtCore.Qt.Key_Enter:
            # 屏蔽窗口的回车响应 ok按钮
            # 如果是回车键，则不执行任何操作，即屏蔽回车响应
            return
        # 对于其他按键，调用基类的 keyPressEvent
        super().keyPressEvent(event)


class LabelManageDialog(QtWidgets.QDialog):
    def __init__(self, parent=None, col=5) -> None:
        super().__init__(parent)
        # 设置对话框标题
        self.setWindowTitle(self.tr("标签管理"))
        self.setModal(True)
        # 创建添加属性按钮
        self.add_label_bt = QtWidgets.QPushButton(self.tr("添加标签"), self)
        self.label_bt_map = {}
        # 添加属性按钮
        self.add_label_bt.clicked.connect(self.addLabelClick)
        # 垂直布局
        self.v_layout = QtWidgets.QVBoxLayout()
        # 网格布局
        self.grid_layout = QtWidgets.QGridLayout()
        # 把添加属性按钮添加到布局的一个位置
        self.grid_layout.addWidget(self.add_label_bt, 0, 0)

        # 定义标签的数量
        self.label_num = 0
        # 定义每行显示的数量
        self.col = col
        #
        self.categories = {}
        # 确认取消按钮
        self.buttonBox = QtWidgets.QDialogButtonBox(
            QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel,
            QtCore.Qt.Horizontal,
            self
        )
        self.buttonBox.accepted.connect(self.onAccepted)
        self.buttonBox.rejected.connect(self.reject)

        self.v_layout.addLayout(self.grid_layout)
        self.v_layout.addWidget(self.buttonBox)

        # 设置对话框的布局
        self.setLayout(self.v_layout)

    def onAccepted(self):
        self.accept()

    def click_label_bt(self):
        # 获取发送信号的对象
        sender = self.sender()
        label_name = sender.text()
        label_info = self.categories[label_name]
        label_dlg = CreateLabelDialog(self)
        label_dlg.loadLabel(label_info)
        if label_dlg.exec():
            # 确认按钮
            ret = label_dlg.getLabelData()
        else:
            # 取消按钮或者关闭对话框
            return
        self.categories[ret["name"]] = ret

    def addLabelClick(self):

        self.addLabel()

    def addLabel(self, name=None):
        """添加标签"""
        if name is None:
            # self.hide()
            label_dlg = CreateLabelDialog(self)
            label_dlg.loadLabel()
            ret = None
            if label_dlg.exec():
                ret = label_dlg.getLabelData()
            else:
                return
            if ret is None:
                return
            self.categories[ret["name"]] = ret
            label_name = ret["name"]
        else:
            label_name = name
            ret = self.categories[name]
        current_button = ColorButton(label_name, ret["color"], self)
        current_button.clicked.connect(self.click_label_bt)
        self.label_bt_map[label_name] = current_button
        # 计算行号
        row = (self.label_num + 1) // self.col
        # 计算列号
        col = (self.label_num + 1) % self.col
        # 把按钮添加到布局里
        self.grid_layout.addWidget(current_button, row, col)

        # 更新标签数量
        self.label_num += 1

    def loadLabel(self, label_info=None):
        """以json文件创建窗口控件"""
        if label_info is not None:
            for onelabel in label_info:
                self.categories[onelabel["name"]] = onelabel
                self.addLabel(onelabel["name"])

    def getLabelData(self):
        ret = []
        for key, value in self.categories.items():
            ret.append(value)
        return ret


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ex = CreateLabelDialog()
    ex.show()
    sys.exit(app.exec_())
